// pc版的 基于canvas的 签名
export default class Signature {
  #points = []  // 路径集合
  #canvas = null  // canvas元素
  #canvasParentElement = null  // canvas元素的父元素
  #ctx = null // 画笔
  #paintWidth = 2 // 画笔宽度
  #paintColor = 'black' // 画笔颜色
  #paintLineCaP = 'round' // 画笔端点形状 (butt: 默认值，端点是垂直于线段边缘的平直边缘) (round：端点是在线段边缘处以线宽为直径的半圆) (square：端点是在选段边缘处以线宽为长、以一半线宽为宽的矩形。)
  #top = 0
  #left = 0
  #id = 0 // 每次绘制的id  为了清除上一次绘制
  #record = [] // 绘制线记录
  constructor(elementId, params = { lineWidth: 2, lineColor: 'black', lineCap: 'round' }) {
    let T = this
    T.#paintWidth = params.lineWidth ? params.lineWidth : T.#paintWidth
    T.#paintColor = params.lineColor ? params.lineColor : T.#paintColor
    T.#paintLineCaP = params.lineCap ? params.lineCap : T.#paintLineCaP
    T.#canvas = document.getElementById(elementId)
    T.#init(T)
    T.#mouseDown(T)
    T.#mouseUp(T)
    // 监听视口变化
    T.#resize(T)
    // 监听父元素变化
    T.#parentChange(T)
  }

  #resize = (T) => {
    window.addEventListener('resize', () => {
      T.#ctx.clearRect(0, 0, T.#canvas.width, T.#canvas.height)
      T.#points = []
      T.#record = []
      T.#init(T)
    })
  }

  #parentChange = (T) => {
    let timer = null
    let ob = new ResizeObserver((entries) => {
      if(timer) clearTimeout(timer)
      timer = setTimeout(() => {
        T.#ctx.clearRect(0, 0, T.#canvas.width, T.#canvas.height)
        T.#points = []
        T.#record = []
        T.#init(T)
      }, 40)
      
    }).observe(T.#canvasParentElement)
  }

  #init = (T) => {
    T.#canvasParentElement = T.#canvas.parentElement
    T.#canvas.width = T.#canvasParentElement.getBoundingClientRect().width
    T.#canvas.height = T.#canvasParentElement.getBoundingClientRect().height
    T.#ctx = T.#canvas.getContext('2d')  //获取绘制画笔
    T.#top = T.#canvas.getBoundingClientRect().top
    T.#left = T.#canvas.getBoundingClientRect().left
  }

  // 鼠标按下事件
  #mouseDown = (T) => {
    T.#canvas.addEventListener('mousedown', e => {
      T.#id++
      let startX = e.clientX - T.#left;
      let startY = e.clientY - T.#top;
      let startPoint = {
        X: startX,
        Y: startY,
        id: T.#id
      }
      T.#points.push(startPoint)
      T.#record.push(startPoint)
      T.#ctx.beginPath()
      T.#ctx.lineWidth = T.#paintWidth
      T.#ctx.strokeStyle = T.#paintColor
      T.#ctx.lineCap = T.#paintLineCaP
      T.#mouseMove(T)
    })
  }

  #mouseUp = (T) => {
    T.#canvas.addEventListener('mouseup', () => {
      T.#points = []
      T.#canvas.removeEventListener('mousemove', T.#moveFn)
    })

    T.#canvas.addEventListener('mouseleave', () => {
      T.#points = []
      T.#canvas.removeEventListener('mousemove', T.#moveFn)
    })
  }

  // 鼠标移动事件
  #mouseMove = (T) => {
    let fn = (e) => {
      let moveX = e.clientX - T.#left;
      let moveY = e.clientY - T.#top;
      let movePoint = {
        X: moveX,
        Y: moveY,
        id: T.#id
      }
      T.#points.push(movePoint)
      T.#record.push(movePoint)
      let len = T.#points.length
      if (len >= 2) {
        T.#draw(T) // 绘制线
      }
    }
    T.#canvas.addEventListener('mousemove', fn)
    T.#moveFn = fn
  }

  #moveFn = () => {}

  #draw = (T) => {
    let point1 = T.#points[0]
		let point2 = T.#points[1]
		T.#points.shift()
		T.#ctx.moveTo(point1.X, point1.Y)
		T.#ctx.lineTo(point2.X, point2.Y)
		T.#ctx.stroke()
  }

  // 清除画布的钩子
  clear = () => {
    this.#ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height)
    this.#record = []
  }

  // 清除上一步
  back = () => {
    if(this.#record.length === 0) return
    let lastId = this.#record[this.#record.length - 1].id
    // 再绘制
    this.#record = this.#record.filter(item => item.id !== lastId)
    // 先清除
    this.#ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height)
    this.#ctx.beginPath()
    this.#record.reduce((prev, curr) => {
      // console.log(prev, curr);
      if(prev.id !== curr.id){
        this.#ctx.beginPath()
      }else{
        this.#ctx.moveTo(prev.X, prev.Y)
        this.#ctx.lineTo(curr.X, curr.Y)
        this.#ctx.stroke()
      }
      return curr
    }, this.#record[0])
  }

  // 导出为base64
  toBase64 = () => {
    if(this.#record.length === 0) return '您还没有签名!!'
    let tempSrc = this.#canvas.toDataURL("image/png");
    return tempSrc
  }

  // 导出为文件流
  toFile = (fileName = 'toFile') => {
    if(this.#record.length === 0) return '您还没有签名!!'
    let tempSrc = this.#canvas.toDataURL("image/png");
    const dataArr = tempSrc.split(",");
    const byteString = atob(dataArr[1]);
    const options = {
      type: "image/jpeg",
      endings: "native"
    };
    const u8Arr = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++) {
      u8Arr[i] = byteString.charCodeAt(i);
    }
    return new File([u8Arr], fileName + ".jpg", options);//返回文件流
  }
}